#include "cvariant.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// 手动实现strndup以兼容Windows平台
static char* strndup(const char* s, size_t n) {
    if (s == NULL) return NULL;
    
    // 计算实际需要复制的长度（不超过n且不超过原字符串长度）
    size_t len = strlen(s);
    if (n < len) len = n;
    
    // 分配内存（+1用于存储终止符）
    char* result = (char*)malloc(len + 1);
    if (result == NULL) return NULL;
    
    // 复制字符串并添加终止符
    memcpy(result, s, len);
    result[len] = '\0';
    return result;
}

// 配置项节点（存储键值对）
typedef struct ConfigNode {
    char* section;         // 节名（如"server"）
    char* key;             // 键名（如"port"）
    CVariant* value;       // 值（多类型存储）
    struct ConfigNode* next; // 链表下一个节点
} ConfigNode;

// 解析上下文
typedef struct {
    ConfigNode* head;      // 配置项链表头
    char* current_section; // 当前解析的节名
} ConfigParser;

// 初始化解析器
static ConfigParser* parser_init() {
    ConfigParser* parser = (ConfigParser*)malloc(sizeof(ConfigParser));
    parser->head = NULL;
    parser->current_section = NULL;
    return parser;
}

// 释放解析器资源
static void parser_free(ConfigParser* parser) {
    ConfigNode* node = parser->head;
    while (node) {
        ConfigNode* next = node->next;
        free(node->section);
        free(node->key);
        cvariant_destroy(node->value);
        free(node);
        node = next;
    }
    free(parser->current_section);
    free(parser);
}

// 去除字符串首尾空格
static char* trim(char* str) {
    if (!str) return NULL;
    // 去除开头空格
    while (isspace((unsigned char)*str)) str++;
    // 去除结尾空格
    if (*str) {
        char* end = str + strlen(str) - 1;
        while (end > str && isspace((unsigned char)*end)) end--;
        *(end + 1) = '\0';
    }
    return str;
}

// 识别值类型并存储到variant
static void set_value_by_type(CVariant* var, const char* value_str) {
    char* endptr;
    // 尝试识别为布尔值
    if (strcmp(value_str, "true") == 0 || strcmp(value_str, "yes") == 0) {
        cvariant_set_int(var, 1); // 1表示true
        return;
    }
    if (strcmp(value_str, "false") == 0 || strcmp(value_str, "no") == 0) {
        cvariant_set_int(var, 0); // 0表示false
        return;
    }
    // 尝试识别为整数
    long int_val = strtol(value_str, &endptr, 10);
    if (*endptr == '\0') {
        cvariant_set_int(var, (int)int_val);
        return;
    }
    // 尝试识别为浮点数
    double float_val = strtod(value_str, &endptr);
    if (*endptr == '\0') {
        cvariant_set_double(var, float_val);
        return;
    }
    // 尝试识别为带引号的字符串（去除引号）
    if (value_str[0] == '"' && value_str[strlen(value_str)-1] == '"') {
        char* str_val = strndup(value_str + 1, strlen(value_str) - 2);
        cvariant_set_str(var, str_val);
        free(str_val);
        return;
    }
    // 否则视为普通字符串
    cvariant_set_str(var, value_str);
}

// 添加配置项到链表
static void add_config_node(ConfigParser* parser, const char* key, const char* value) {
    if (!parser->current_section || !key || !value) return;

    ConfigNode* node = (ConfigNode*)malloc(sizeof(ConfigNode));
    node->section = strdup(parser->current_section);
    node->key = strdup(key);
    node->value = cvariant_create();
    set_value_by_type(node->value, value); // 自动识别类型
    node->next = parser->head;
    parser->head = node;
}

// 解析INI文件
static int parse_ini_file(ConfigParser* parser, const char* filename) {
    FILE* f = fopen(filename, "r");
    if (!f) {
        fprintf(stderr, "无法打开文件: %s\n", filename);
        return -1;
    }

    char line[1024];
    int line_num = 0;
    while (fgets(line, sizeof(line), f)) {
        line_num++;
        char* content = trim(line);
        // 跳过空行和注释
        if (*content == '\0' || *content == ';' || *content == '#') continue;
        // 解析节名（如[server]）
        if (*content == '[' && content[strlen(content)-1] == ']') {
            free(parser->current_section);
            parser->current_section = strndup(content + 1, strlen(content) - 2);
            continue;
        }
        // 解析键值对（如port=8080）
        char* eq_pos = strchr(content, '=');
        if (eq_pos) {
            *eq_pos = '\0';
            char* key = trim(content);
            char* value = trim(eq_pos + 1);
            add_config_node(parser, key, value);
        } else {
            fprintf(stderr, "警告: 无效行 %d: %s\n", line_num, content);
        }
    }
    fclose(f);
    return 0;
}

// 查询配置项
static int query_config(ConfigParser* parser, const char* query) {
    // 拆分查询为节名和键名（格式：section.key）
    char* dot_pos = strchr(query, '.');
    if (!dot_pos) {
        fprintf(stderr, "查询格式错误，应为: 节名.键名\n");
        return -1;
    }
    char* section = strndup(query, dot_pos - query);
    char* key = strdup(dot_pos + 1);

    // 遍历链表查找配置项
    ConfigNode* node = parser->head;
    while (node) {
        if (strcmp(node->section, section) == 0 && strcmp(node->key, key) == 0) {
            // 根据类型输出值
            switch (cvariant_get_type(node->value)) {
                case TYPE_INT:
                    // 布尔值特殊处理
                    if (strcmp(key, "enable") == 0 || strcmp(key, "active") == 0) {
                        printf("%s\n", cvariant_get_int(node->value) ? "true" : "false");
                    } else {
                        printf("%d\n", cvariant_get_int(node->value));
                    }
                    break;
                case TYPE_DOUBLE:
                    printf("%g\n", cvariant_get_double(node->value));
                    break;
                case TYPE_STR:
                    printf("%s\n", cvariant_get_str(node->value));
                    break;
                default:
                    printf("未知类型\n");
            }
            free(section);
            free(key);
            return 0;
        }
        node = node->next;
    }

    fprintf(stderr, "未找到配置项: %s\n", query);
    free(section);
    free(key);
    return -1;
}

// 列出所有配置项
static void list_all_configs(ConfigParser* parser) {
    ConfigNode* node = parser->head;
    while (node) {
        printf("[%s] %s = ", node->section, node->key);
        // 根据类型输出值
        switch (cvariant_get_type(node->value)) {
            case TYPE_INT:
                printf("%d (int)\n", cvariant_get_int(node->value));
                break;
            case TYPE_DOUBLE:
                printf("%g (float)\n", cvariant_get_double(node->value));
                break;
            case TYPE_STR:
                printf("%s (string)\n", cvariant_get_str(node->value));
                break;
        }
        node = node->next;
    }
}

// 显示帮助
static void print_help(const char* progname) {
    printf("用法: %s [选项] <INI文件> [查询]\n", progname);
    printf("解析INI配置文件并查询值（兼容Linux风格）\n");
    printf("选项:\n");
    printf("  -l        列出文件中所有配置项及类型\n");
    printf("  -h        显示帮助信息\n");
    printf("查询格式: 节名.键名（如 'server.port'）\n");
    printf("示例:\n");
    printf("  %s config.ini server.port      # 查询[server]节的port值\n", progname);
    printf("  %s -l app.ini                 # 列出app.ini所有配置项\n", progname);
    printf("  %s settings.ini log.enable    # 查询[log]节的enable值（布尔型）\n", progname);
}

int main(int argc, char* argv[]) {
    if (argc < 2) {
        print_help(argv[0]);
        return 1;
    }

    int list_mode = 0;
    const char* filename = NULL;
    const char* query = NULL;

    // 解析命令行参数
    if (strcmp(argv[1], "-h") == 0) {
        print_help(argv[0]);
        return 0;
    } else if (strcmp(argv[1], "-l") == 0) {
        if (argc < 3) {
            print_help(argv[0]);
            return 1;
        }
        list_mode = 1;
        filename = argv[2];
    } else {
        filename = argv[1];
        query = (argc >= 3) ? argv[2] : NULL;
        if (!query) {
            print_help(argv[0]);
            return 1;
        }
    }

    // 解析配置文件
    ConfigParser* parser = parser_init();
    if (parse_ini_file(parser, filename) != 0) {
        parser_free(parser);
        return 1;
    }

    // 执行操作
    if (list_mode) {
        list_all_configs(parser);
    } else {
        query_config(parser, query);
    }

    // 清理资源
    parser_free(parser);
    return 0;
}
